package main

import (
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric-chaincode-go/shim"
	"github.com/hyperledger/fabric-protos-go/peer"
)

// Tobacco 烟草结构体
type Tobacco struct {
	ObjectType string `json:"ObjectType"`
	TraceId    string `json:"TraceId"`  //溯源码
	Type       string `json:"Type"`     // 烟草类型
	Source     string `json:"Source"`   //烟草来源
	AstaffId   string `json:"AStaffId"` //烟草物流中心的操作员工信息
	BstaffId   string `json:"BStaffId"` //售卖商户的操作员工信息
	Date       string `json:"Date"`     // 生产日期
	Quality    string `json:"Quality"`  // 质量等级

	Location string `json:"Location"`
	State    string `json:"State"` //状态  1->表示在烟草配送中心  2->表示在商户当中 3->表示已经售出
}

// Staff 员工结构体
type Staff struct {
	ObjectType string   `json:"ObjectType"`
	Id         string   `json:"Id"`
	Name       string   `json:"Name"`
	Asset      []string `json:"Asset"` //处理的烟草溯源码集合
}

// QueryResult 获取所有员工结果
type QueryResult struct {
	Key    string `json:"Key"`
	Record *Staff `json:"Value"`
}

type Chaincode struct {
}

func (t *Chaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
	fmt.Println(" ==== Init ====")
	return shim.Success(nil)
}
func (t *Chaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
	// 获取用户意图
	fun, args := stub.GetFunctionAndParameters()
	if fun == "updateTobacco" {
		return t.updateTobacco(stub, args) // 添加信息
	} else if fun == "query1" {
		return t.query1(stub, args)
	} else if fun == "query2" {
		return t.query2(stub, args)
	} else if fun == "addStaff" {
		return t.addStaff(stub, args)
	} else if fun == "queryStaff" {
		return t.queryStaff(stub, args)
	} else if fun == "queryAllStaff" {
		return t.queryAllStaff(stub)
	}
	return shim.Error("指定的函数名称错误")

}

const DOC_TYPE = "tobaccoObj"
const Staff_TYPE = "StaffObj"

func PutPro(stub shim.ChaincodeStubInterface, tobacco Tobacco) ([]byte, bool) {

	tobacco.ObjectType = DOC_TYPE
	b, err := json.Marshal(tobacco)
	if err != nil {
		return nil, false
	}

	//KEY(溯源码) -> VALUE(烟草数据)
	err = stub.PutState(tobacco.TraceId+"_"+tobacco.State, b)

	if err != nil {
		return nil, false
	}
	return b, true
}

func PutStaff(stub shim.ChaincodeStubInterface, staff Staff) ([]byte, bool) {

	staff.ObjectType = Staff_TYPE
	b, err := json.Marshal(staff)
	if err != nil {
		return nil, false
	}

	//KEY(员工id) -> VALUE(员工信息)
	err = stub.PutState(staff.Id, b)

	if err != nil {
		return nil, false
	}
	return b, true
}

// 烟草局收存中心 上传烟草信息
func (t *Chaincode) updateTobacco(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	if len(args) != 2 {
		return shim.Error("给定的参数个数不符合要求")
	}
	//富查询
	var tobacco Tobacco

	err := json.Unmarshal([]byte(args[0]), &tobacco)

	if err != nil {
		return shim.Error("反序列化信息时发生错误")
	}

	_, bl := PutPro(stub, tobacco)
	if !bl {
		return shim.Error("保存信息时发生错误")
	}

	err = stub.SetEvent(args[1], []byte{})
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success([]byte("信息添加成功"))
}

// 根据溯源码查询 第一阶段 即在商户获取接口
func (t *Chaincode) query1(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	// 查询
	b, _ := stub.GetState(args[0])
	return shim.Success(b)
}

// 根据溯源码查询 第二阶段 即在监管部门或消费者
func (t *Chaincode) query2(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	// 查询
	b, _ := stub.GetState(args[0])
	return shim.Success(b)
}

// 获取员工信息
func (t *Chaincode) queryStaff(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	b, _ := stub.GetState(args[0])
	return shim.Success(b)
}

func (t *Chaincode) addStaff(stub shim.ChaincodeStubInterface, args []string) peer.Response {

	if len(args) != 2 {
		return shim.Error("给定的参数个数不符合要求")
	}
	//富查询
	var staff Staff

	err := json.Unmarshal([]byte(args[0]), &staff)

	if err != nil {
		return shim.Error("反序列化信息时发生错误")
	}

	_, bl := PutStaff(stub, staff)
	if !bl {
		return shim.Error("保存信息时发生错误")
	}

	err = stub.SetEvent(args[1], []byte{})
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success([]byte("信息添加成功"))
}

func (t *Chaincode) queryAllStaff(stub shim.ChaincodeStubInterface) peer.Response {
	startKey := ""
	endKey := ""

	resultsIterator, err := stub.GetStateByRange(startKey, endKey)

	if err != nil {
		return shim.Error("error")
	}
	defer resultsIterator.Close()

	var results []QueryResult

	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()

		if err != nil {
			return shim.Error("错了")
		}

		b := new(Staff)
		_ = json.Unmarshal(queryResponse.Value, b)

		queryResult := QueryResult{Key: queryResponse.Key, Record: b}
		results = append(results, queryResult)
	}
	jsontex, _ := json.Marshal(results)
	return shim.Success(jsontex)
}

//func (t *Chaincode) takeTx(stub shim.ChaincodeStubInterface, args []string) peer.Response {
//
//	if len(args) != 2 {
//		return shim.Error("给定的参数个数不符合要求")
//	}
//	var tx Tx
//	_ = json.Unmarshal([]byte(args[0]), &tx)
//
//	fromadd, _ := stub.GetState(tx.FromAdd)
//	toadd, _ := stub.GetState(tx.ToAdd)
//
//	var fromwallet Wallet
//	var towallet Wallet
//
//	_ = json.Unmarshal(fromadd, &fromwallet)
//	_ = json.Unmarshal(toadd, &towallet)
//
//	fromamount, _ := strconv.ParseFloat(fromwallet.Amount, 20)
//	toamount, _ := strconv.ParseFloat(towallet.Amount, 20)
//
//	//交易数额
//	txamount, _ := strconv.ParseFloat(tx.Amount, 20)
//
//	if txamount > fromamount {
//		return shim.Error("tx failed,u dont hava enough timecoin")
//	}
//
//	resultsfrom := fromamount - txamount
//	resultsto := toamount + txamount
//
//	fromwallet.Amount = strconv.FormatFloat(resultsfrom, 'f', 10, 20)
//	towallet.Amount = strconv.FormatFloat(resultsto, 'f', 10, 20)
//
//	fromwalletb, _ := json.Marshal(fromwallet)
//	towalletb, _ := json.Marshal(towallet)
//
//	_ = stub.PutState(fromwallet.Bcos_add, fromwalletb)
//	_ = stub.PutState(towallet.Bcos_add, towalletb)
//
//	_ = stub.PutState(tx.Txid, []byte(args[0]))
//
//	return shim.Success([]byte("INSERT SUCCESS"))
//}

func main() {
	err := shim.Start(new(Chaincode))
	if err != nil {
		fmt.Printf("启动烟草溯源时发生错误: %s", err)
	}
}
